package yxk.task.utils;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.hr.hbp.common.util.HRDynamicObjectUtils;
import kd.sdk.wtc.wtpm.business.punchcard.WTPMPunchCardHelper;
import yxk.utils.DateUtil;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

public class BusitripseServiceMethod {
    private static Log logger = LogFactory.getLog(BusitripseServiceMethod.class);

    private static BusitripseServiceMethod INS = new BusitripseServiceMethod();

    public static BusitripseServiceMethod getInstance() {
        return INS;
    }
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat forma = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    public void addBusitripselfEntry(Map<String,String> map, Map param, DynamicObjectCollection collection){
        Date startTime;
        Date endTime;
        try {
            startTime = forma.parse(DateUtil.getISO8601Timestamp(map.get("startTime")));//客开出差单开始时间
            endTime = forma.parse(DateUtil.getISO8601Timestamp(map.get("endTime")));//客开出差单结束时间
        } catch (Exception e) {
           logger.error("BusitripseServiceMethod.addBusitripselfEntry.eTime:{}",e);
           return;
        }

        Calendar cal=Calendar.getInstance();
        Map<String,Date> mapCalendar = new HashMap();
        String number = param.get("sceneNumber").toString();
        Date workStar = (Date)param.get("star"); //班次开始时间
        Date workEnd = (Date)param.get("end"); //班次结束时间
        logger.info("标品出差分录日期拆分规则：{}，分录获取的参数：{}",number,String.format("startTime:%s,endTime:%s",forma.format(startTime),forma.format(endTime)));
        map.put("scene",number);
        // 开始时间和结束时间并结合时间类型，判断场景：时间类型,对标标品的时间类型，0：上半天，1：下半天，2：全天，3：自选时段
        switch (number){
            //开始时间和结束时间都为全天
            case "v1":
                map.put("type","2");
                mapCalendar.put("startTime",startTime);
                mapCalendar.put("endTime",endTime);
                setCollection(collection,map,mapCalendar,formatter);
                break;
            //开始时间为全天/结束时间为自定义
            case "v2":
                //获取当前日期的前一天
                mapCalendar.put("startTime",startTime);
                map.put("type","2");
                cal.setTime(workEnd);
                cal.add(Calendar.DATE,-1);
                mapCalendar.put("endTime",cal.getTime());
                setCollection(collection,map,mapCalendar,formatter);
                //结束时间为自定义
                mapCalendar.put("startTime",getZero(endTime));
                map.put("type","3");
                map.put("dateType","2");
                mapCalendar.put("endTime",endTime);
                setCollection(collection,map,mapCalendar,forma);
                break;

            //开始时间为自定义/结束时间为全天
            case "v3":
                //第一条数据  开始日期 和 结束日期为同一天
                mapCalendar.put("startTime",startTime);
                map.put("type","3");
                map.put("dateType","1");
                Date end = getEnd(startTime);
                mapCalendar.put("endTime",end);
                setCollection(collection,map,mapCalendar,forma);

                //第二条数据 开始日期的第二天至结束时间
                cal.setTime(workStar);
                cal.add(Calendar.DATE,1);
                mapCalendar.put("startTime",cal.getTime());
                map.put("type","2");
                mapCalendar.put("endTime",endTime);
                setCollection(collection,map,mapCalendar,formatter);
                break;

            //开始时间和结束时间都为自定义
            case "v4":
                //第一条数据  开始日期 和 结束日期为同一天
                Date install = getEnd(startTime);
                cal.setTime(install);
                mapCalendar.put("startTime",startTime);
                map.put("type","3");
                map.put("dateType","1");
                mapCalendar.put("endTime",install);
                setCollection(collection,map,mapCalendar,forma);

                //第二条数据 开始日期的第二天至结束时间的前一天
                cal.setTime(workStar);
                cal.add(Calendar.DATE,1);
                mapCalendar.put("startTime",getZero(cal.getTime()));
                cal.setTime(workEnd);
                cal.add(Calendar.DATE,-1);
                map.put("type","2");
                mapCalendar.put("endTime",getEnd(cal.getTime()));
                setCollection(collection,map,mapCalendar,formatter);
                //第三条数据 结束时间同一天的开始时间至结束时间
                Date startInstall = getZero(endTime);
                map.put("type","3");
                map.put("dateType","2");
                mapCalendar.put("startTime",startInstall);
                mapCalendar.put("endTime",endTime);
                setCollection(collection,map,mapCalendar,forma);
                break;
            //出差日期为同一天
            case "v5" :
                map.put("type","3");
                mapCalendar.put("startTime",workStar);
                mapCalendar.put("endTime",workEnd);
                setCollection(collection,map,mapCalendar,forma);
                break;
            //出差两天
            case "v6":
                map.put("type", "3");
                map.put("dateType", "1");
                mapCalendar.put("startTime", startTime);
                Date v6end = getEnd(startTime);
                cal.setTime(v6end);
                mapCalendar.put("endTime", cal.getTime());
                setCollection(collection, map, mapCalendar, forma);

                map.put("type", "3");
                map.put("dateType", "2");
                mapCalendar.put("startTime", getZero(endTime));
                mapCalendar.put("endTime", endTime);
                setCollection(collection, map, mapCalendar, forma);
                break;
        }
    }

    public  Map<String,Date> increaseOrDecreaseDate(Long signPersonId,Date startDate,Date endDate,int type){
        Map<String, Date> dateMap;
        logger.info("BusitripseServiceMethod.increaseOrDecreaseDate.startDate:{};endDate{};type:{}",forma.format(startDate),forma.format(endDate),type);
        if(type == 1){
            dateMap = increaseOffDate(signPersonId, startDate, type);
        }else {
            dateMap = increaseOffDate(signPersonId,endDate,type);
        }
        logger.info("BusitripseServiceMethod.increaseOrDecreaseDate.dateMap:{}",dateMap);
        return  dateMap;
    }

    private Map<String,Date> increaseOffDate(Long signPersonId,Date startDate,int type){
        Calendar instance = Calendar.getInstance();
        //判断出差班次是OFF班 、是OFF就往前一天查看是否是夜班
        Map<String, Date> dateMap = startCardDetail(signPersonId, startDate,type,true);
        if(dateMap == null ) {
            instance.setTime(startDate);
            instance.set(Calendar.DATE, instance.get(Calendar.DATE) - 1);
            //判断当前班次是否在前一天班次内
            Map<String, Date> dayDateMap = startCardDetail(signPersonId, instance.getTime(), type, false);
            Map<String, Date> stringDateMap = setOwnDate(dayDateMap, startDate, type);
            if (stringDateMap != null && stringDateMap.size() > 0) {
                return stringDateMap;
            } else {
                //为空就是off班
                return null;
            }
        }
        return dateMap;
    }



    /***
     * 开始排班/开始结束时间
     * @param signPersonId
     * @param parseDate
     * @param type 1 开始时间/2 结束时间
     * @return
     */

    public Map<String,Date> startCardDetail(Long signPersonId,Date parseDate,int type,Boolean bool){
        Map<String,Date> map=new HashMap();
         Calendar instance = Calendar.getInstance();
        try {
            logger.info("BusitripseServiceMethod.startCardDetail.Person{}",String.format("signPersonId:%s,parseDate:%s,type:%s",signPersonId,forma.format(parseDate),type));
            String format = formatter.format(parseDate);
            Date parse = formatter.parse(format);
            //获取时间的当天班次
            Map<String, Date> dayDateMap = parseCardDetail(signPersonId, parse);
            logger.info("BusitripseServiceMethod.startCardDetail.dayDateMap{}",dayDateMap);
            if(dayDateMap == null  ||  dayDateMap.size() == 0 ){
                return null;
            }
            Date startDate = dayDateMap.get("start");//当前班次的开始时间
            Date entDate = dayDateMap.get("end");//当天班次结束时间
            if(bool) {
                //获取是否是班次类的时间
                Map<String, Date> stringDateMap = setOwnDate(dayDateMap, parseDate, type);
                if (stringDateMap != null) {
                    return stringDateMap;
                }
            }else{
                map.put("owndate", startDate);
                map.put("start", startDate);
                map.put("end", entDate);
                map.put("ownEndDate",entDate);
                return map;
            }
            //场景：出差时间开始时间小于于当天班次的开始时间
            if(startDate.getTime() > parseDate.getTime()){
                instance.setTime(parse);
                instance.set(Calendar.DATE,instance.get(Calendar.DATE)-1);
                //获取时间的前一天班次
                Map<String, Date> dateMap = parseCardDetail(signPersonId, instance.getTime());
                logger.info("BusitripseServiceMethod.startCardDetail.dateMap{}",dateMap);
                if(dayDateMap == null && dateMap == null){
                    return null;
                }
                Map<String, Date> ownDate = setOwnDate(dateMap, parseDate, type);
                if(ownDate != null){
                    return ownDate;
                }else {
                    if(type == 1){
                        map.put("owndate", startDate);
                        map.put("start", startDate);
                        map.put("end", entDate);
                        map.put("ownEndDate",entDate);

                    }else {
                        map.put("owndate", instance.getTime());
                        map.put("start", dateMap.get("start"));
                        map.put("end",dateMap.get("end"));
                        map.put("ownEndDate",dateMap.get("end"));

                    }
                    return map;
                }
            }
            //场景：开始时间大于当天班次的结束时间
            if(parseDate.getTime() > entDate.getTime()){
                if(type == 1) {
                    instance.setTime(parse);
                    instance.set(Calendar.DATE, instance.get(Calendar.DATE) + 1);
                    //获取后一天班次时间
                    Map<String, Date> mobydateMap = parseCardDetail(signPersonId, instance.getTime());
                    if(mobydateMap == null){
                        return null;
                    }
                    logger.info("BusitripseServiceMethod.startCardDetail.mobydateMap{}",mobydateMap);
                    map.put("owndate", instance.getTime());
                    map.put("start", mobydateMap.get("start"));
                    map.put("end",mobydateMap.get("end"));
                    map.put("ownEndDate",mobydateMap.get("end"));
                }else{
                    map.put("owndate", parse);
                    map.put("start", startDate);
                    map.put("end", entDate);
                    map.put("ownEndDate",entDate);
                }
            }

        }catch (Exception e){
            logger.info("BusitripseServiceMethod.startCardDetail:{},e:{}","获取开始排班时间错误",e);
        }

        return map;
    }

    private  Map<String,Date> setOwnDate(Map<String, Date> dateMap,Date parseDate ,int type){
        Map<String,Date> map=new HashMap();
        try {
            if(dateMap == null || dateMap.size() == 0){
                return null;
            }
            logger.info("BusitripseServiceMethod.startCardDetail.setOwnDate.dateMap{};parseDate:{};type:{}",dateMap,parseDate,type);
            Date instanceStartDate = dateMap.get("start");
            Date instanceEndDate = dateMap.get("end");
            if(parseDate.getTime() >= instanceStartDate.getTime() && parseDate.getTime() <= instanceEndDate.getTime()){
                map.put("owndate",instanceStartDate);
                map.put("ownEndDate",instanceEndDate);
                if(type == 1){
                    map.put("start",parseDate);
                    map.put("end",instanceEndDate);
                }else {
                    map.put("start",instanceStartDate);
                    map.put("end",parseDate);
                }
                return map;
            }
        }catch (Exception e){
           logger.error("BusitripseServiceMethod.setOwnDate:{}",e);
        }
        return null;
    }


    /***
     * 获取班次开始时间和结束时间
     * @param signPersonId
     * @param date
     * @return
     */
    public Map<String, Date> parseCardDetail(Long signPersonId, Date date){
        Map<String,Date> map=new HashMap<>();
        String format = formatter.format(date);

        //班次开始时间
        Date start=null;
        //班次结束时间
        Date end=null;
        try {
            Map<Date, Map<String, Object>> punchCardDetail = WTPMPunchCardHelper.getPunchCardDetail(signPersonId,formatter.parse(format) , formatter.parse(format) );
            logger.info("BusitripseServiceMethod.punchCardDetail:{}",punchCardDetail);
            Set<Map.Entry<Date, Map<String, Object>>> entries = punchCardDetail.entrySet();
            for (Map.Entry<Date, Map<String, Object>> entry : entries) {
                Map<String, Object> value = entry.getValue();
                logger.info("BusitripseServiceMethod.parseCardDetail.value:{}",value);
                Object offshift = value.get("offshift");
                Boolean off = offshift instanceof String?"true".equals(offshift.toString())?true:false :
                        Boolean.TRUE.equals(offshift)?true:false;
                if(off){
                    return null;
                }
                List<Map<String,String>> listMap= (List<Map<String,String>>) value.get("shift");
                logger.info("BusitripseServiceMethod.parseCardDetail.listMap:{}",listMap);
                for (Map<String, String> row:listMap) {
                    Date startTime = forma.parse(row.get("start"));
                    if(start == null){
                        start = startTime;
                    }else {
                        start =  start.getTime() < startTime.getTime()? start : startTime;
                    }
                    Date endTime = forma.parse(row.get("end"));
                    if(end == null){
                        end=endTime;
                    }else {
                        end =  end.getTime() < endTime.getTime()? endTime : end;
                    }
                }
            }

            map.put("start",start);
            map.put("end",end);

        }catch (Exception e){
            logger.info("BusitripseServiceMethod.parseCardDetail:{}，e:{}","获取打卡服务错误",e);
        }
        return map;
    }

    /**
     *  根据开始时间和结束时间判断生成分录数据的场景
     * @param starTtime  开始时间
     * @param endTime   结束时间
     * @return
     */
    public Map<String, Object> getSceneNumber(Long attId, Date starTtime , Date endTime){
        Map<String, Object> map=new HashMap();
        Map<String, Date> starDateMap = increaseOrDecreaseDate(attId, starTtime,endTime, 1);

        logger.info("BusitripseServiceMethod.getSceneNumber.starDateMap{};",starDateMap);
        Date zero;
        if( starDateMap != null && starDateMap.size()>0){
            zero  = starDateMap.get("start");
        }else{
            zero=starTtime;
        }
        //全天结束日期
        Date end;
        Date endOwnDate;
        Map<String, Date> endDateMap = increaseOrDecreaseDate(attId, starTtime,endTime, 2);
        if (endDateMap!=null && endDateMap.size() > 0){
            end =  endDateMap.get("ownEndDate");
            endOwnDate = endDateMap.get("end");
        }else{
            end = endTime;
            endOwnDate = endTime;
        }
        //获取结束日期的年月日
        String  sceneNumber = null;
        try {
            Long parseTime = formatter.parse(formatter.format(zero)).getTime();
            Long time = formatter.parse(formatter.format(endOwnDate)).getTime();
            Long num=time-parseTime;//时间戳相差的毫秒数
            Long aa= num/24/60/60/1000;
            if(aa==0){
                sceneNumber = "v5";
            }else if(aa == 1){
                sceneNumber = "v6";
            }else
            if(zero.getTime() == starTtime.getTime() && end.getTime()==endTime.getTime()
                    && (starDateMap != null && starDateMap.size() > 0)&& (endDateMap!=null && endDateMap.size() > 0)){
                sceneNumber = "v1";
            }else if(zero.getTime() == starTtime.getTime() && end.getTime()!=endTime.getTime()
                    && (starDateMap != null && starDateMap.size() > 0)){
                sceneNumber = "v2";
            }else if(zero.getTime() != starTtime.getTime() && end.getTime()==endTime.getTime()
                    && (endDateMap!=null && endDateMap.size() > 0)){
                sceneNumber = "v3";
            }else {
                sceneNumber = "v4";
            }
            map.put("sceneNumber",sceneNumber);

        }catch (Exception e){
            e.printStackTrace();
        }

        map.put("star",zero);
        map.put("end",endOwnDate);
        return map;
    }


    /***
     * 分录赋值
     * @param collection 分录数据
     * @param map   填充的数据
     * @param dateMap   传入开始时间和结束时间
     * @param formatter 时间转类型
     */

    public void setCollection(DynamicObjectCollection collection,Map<String,String> map,Map<String,Date> dateMap,SimpleDateFormat formatter){
        try {
            String userID = map.get("userID");
            String tripType = map.get("tripType");//出差类型
            String tripePlace = map.get("tripePlace");//目的地
            String tripeTask = map.get("title");//出差原因
            String type = map.get("type");//时间类型,对标标品的时间类型，0：上半天，1：下半天，2：全天，3：自选时段
            String scene = map.get("scene");//场景
            Date startTime = dateMap.get("startTime");//开始时间
            Date endTime = dateMap.get("endTime");//结束
            String startFormat = formatter.format(startTime);
            String endFormat = formatter.format(endTime);
            logger.info("填充数据参数{}",map);

            logger.info("开始时间和结束时间{}",String.format(String.format("startTime:%s,endTime:%s",startFormat,endFormat)));
            // 时间
            DynamicObject addNew = collection.addNew();
            if(StringUtils.equals(scene,"v5")){
                addNew.set("owndate",formatter.parse(startFormat));
            }else
            if(StringUtils.equals(type,"3")){
                String dateType = map.get("dateType").toString();
                Map<String, Date> cardDate = StringUtils.equals(dateType,"1") ? increaseOrDecreaseDate(Long.parseLong(userID), startTime,endTime, 1) : increaseOrDecreaseDate(Long.parseLong(userID), startTime,endTime, 2);
                logger.info("BusitripseServiceMethod.setCollection.cardDate:{}",cardDate);
                if(cardDate != null && cardDate.size() > 0) {
                    startTime = cardDate.get("start");
                    endTime = cardDate.get("end");
                    startFormat = formatter.format(startTime);
                    endFormat = formatter.format(endTime);
                    addNew.set("owndate", cardDate.get("owndate"));
                }else {
                    addNew.set("owndate", startTime);
                }
            }

            addNew.set("busitriptype", tripType);//出差类型
            addNew.set("startdatestr",startFormat);//开始时间文本
            addNew.set("startdate",startTime);//开始时间
            addNew.set("enddatestr",endFormat);//结束时间文本
            addNew.set("enddate",endTime);//结束时间
            logger.info("enddatestr:{},enddate{},startdatestr{},startdate{}",endFormat,endTime,startFormat,startTime);
            addNew.set("to",tripePlace);//目的他
            addNew.set("tripresontex",tripeTask);//出差原因
            addNew.set("unit","A");
            int tripTime = DateUtil.getTimeDifference(startFormat, endFormat);
            addNew.set("triptime", tripTime);
            addNew.set("startmethod",type);//开始日期类型
            addNew.set("endmethod",type);//结束日期类型

        }catch (Exception e){
            logger.info("BusitripseServiceMethod.setCollection:{}",e);
        }
    }

    /***
     * 附件复制
     * @param parentId 原单ID
     * @param pkValue   单据ID
     * @param entityName 单据标识
     */
    public void copyAttachment(Long parentId,Long pkValue,String entityName) {

        HRBaseServiceHelper helper = new HRBaseServiceHelper("bos_attachment");
        QFilter filter = new QFilter("finterid", "=", parentId.toString());
        DynamicObject[] originalAttachments = helper.loadDynamicObjectArray(new QFilter[]{filter});
        if (originalAttachments != null && originalAttachments.length != 0) {
            DynamicObject[] attachments = new DynamicObject[originalAttachments.length];

            for(int i = 0; i < originalAttachments.length; ++i) {
                DynamicObject attachment = originalAttachments[i];
                DynamicObject newAttachment = helper.generateEmptyDynamicObject();
                HRDynamicObjectUtils.copy(attachment, newAttachment);
                newAttachment.set("fbilltype", entityName);
                newAttachment.set("finterid", pkValue);
                attachments[i] = newAttachment;
            }

            helper.save(attachments);
        }
    }

    /***
     * 给表头获取时间
     * @param entr
     * @param row
     */
    public void minDateTime(DynamicObjectCollection entr,DynamicObject row){
        String nuits="A";
        if(entr!=null){
            Date start=null;//开始时间
            Date end=null;//结束时间
            BigDecimal sum=BigDecimal.ZERO;
            for (DynamicObject key:entr){
                sum=sum.add(key.getBigDecimal("triptime"));
                try {
                    Date statDate = key.getDate("startdate");//开始时间
                    Date endDate = key.getDate("enddate");//结束时间
                    if(start==null){
                        start=statDate;
                    }else {
                        start=start.getTime()<statDate.getTime()?start:statDate;
                    }
                    if(end==null){
                        end=endDate;
                    }else{
                        end=end.getTime()<endDate.getTime()?endDate:end;
                    }
                }catch (Exception exc){
                    exc.printStackTrace();
                    logger.error(String.format("数据分录异常：%s",exc));
                }

            }
            row.set("sdate",start);//开始日期
            row.set("edate",end);//结束日期
            row.set("sumunit",nuits);//单位
            row.set("sumtriptime",sum);
            logger.info(String.format("数据参数：%s",row));
        }
    }


    /**
     * 获得当日0点
     */
    public static Date getZero(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }
    /**
     * 获得当日最后时间
     */
    public static Date getEnd(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }
}
